﻿using System;
using System.Timers;

namespace xyPlot
{
    /// <summary>
    /// A simple simulator to simulate some live data. The new
    /// data will only be added to to the graph via an ObservableCollection
    /// if the Graph.CanAcceptNewStreamingReadings is set to true.
    /// The Graph can be panned left/right, and when it is panning it WILL
    /// not accept new values, as it is effectively in a paused state
    /// 
    /// You should write a proper DataProvider that works simliar to this, in fact
    /// the only part that I would change is how the values are obtained, otherwise 
    /// this object is sound and works as it should
    /// </summary>
    public class DataValueSimulator
    {

        #region Data

        private ThreadSafeObservableCollection<GraphDataItem> dataValues = null;
        private Timer timer = new Timer(100);
        private Random rand = new Random(50);
        private Int32 SamplesWindowSize = 50;
        //private WPFTickerDataContext dataContext = new WPFTickerDataContext();
        private long currentSampleCounter = 0;
        private Boolean SupportsHistoricalData = true;

        #endregion

        #region Ctor
        public DataValueSimulator()
        {
            dataValues = new ThreadSafeObservableCollection<GraphDataItem>();

            //Obtain the settings from the stored settings, these can be changed
            //via the app.config
            SamplesWindowSize = 
                xyPlot.Properties.Settings.Default.SAMPLE_WINDOW_SIZE;

            timer.Interval = 
                xyPlot.Properties.Settings.Default.SAMPLE_INTERVAL_IN_MS;

            SupportsHistoricalData = 
                xyPlot.Properties.Settings.Default.SUPPORTS_HISTORICAL_DATA;

        }
        #endregion

        #region Public Methods

        /// <summary>
        /// Creates a new timer and every timer tick, creates a new GraphDataItem
        /// and also determines if an existing GraphDataItem should be removed from
        /// the mantained DataValue, basically only maintain a window of data values
        /// </summary>
        public void Run()
        {
            //Make sure we start out with a blank database for our samples
            //dataContext = new WPFTickerDataContext();
            //dataContext.ExecuteCommand("DELETE FROM TickerSamples");



            timer.Enabled = true;
            timer.Start();
            timer.Elapsed += (s, e) =>
                {
                    if (dataValues.Count == SamplesWindowSize)
                    {
                        dataValues.RemoveAt(0);
                        GC.Collect();
                    }
                    
                    //geta new item based on the values
                    GraphDataItem dataItem = new GraphDataItem
                    {
                        DataValue = (double)rand.NextDouble() * 50,
                        TimeSampled = DateTime.Now,
                        SampleSequenceNumber=currentSampleCounter++
                    };

                    //If Graph is not currently paused, add it to the list
                    //that the Graph uses
                    if (Graph.CanAcceptNewStreamingReadings)
                        dataValues.Add(dataItem);

                    //If the app is configured to allow historcal data
                    //we need to store some historical data in the database
                    if (SupportsHistoricalData)
                    {
                        //dataContext = new WPFTickerDataContext();

                        //Now store the item in the Database, so we can see some historical values
                        //later on if we want to
                        //dataContext.TickerSamples.InsertOnSubmit(
                        //    new TickerSample
                        //    {
                        //        SampleDate = dataItem.TimeSampled,
                        //        SampleValue = dataItem.DataValue,
                        //        SampleSequenceNumber = dataItem.SampleSequenceNumber
                        //    });
                        //dataContext.SubmitChanges();
                    }


                };
        }

        #endregion

        #region IPublic Properties

        public ThreadSafeObservableCollection<GraphDataItem> DataValues
        {
            get { return dataValues; }
            set
            {
                dataValues = value;
            }
        }
        #endregion
    }
}